Рынок заведений общественного питания Москвы¶
Описание проекта¶
Инвесторы из фонда «Shut Up and Take My Money» решили попробовать себя в новой области и открыть заведение общественного питания в Москве. Заказчики ещё не знают, что это будет за место: кафе, ресторан, пиццерия, паб или бар, — и какими будут расположение, меню и цены. Для начала необходимо подготовить исследование рынка Москвы, найти интересные особенности и презентовать полученные результаты, которые в будущем помогут в выборе подходящего инвесторам места. Презентация должна быть информативной и лаконичной. Для исследования доступен датасет с заведениями общественного питания Москвы, составленный на основе данных сервисов Яндекс Карты и Яндекс Бизнес на лето 2022 года. Информация, размещённая в сервисе Яндекс Бизнес, могла быть добавлена пользователями или найдена в общедоступных источниках. Она носит исключительно справочный характер.
Описание данных¶
Файл moscow_places.csv:
- name — название заведения;
- address — адрес заведения;
- category — категория заведения, например «кафе», «пиццерия» или «кофейня»;
- hours — информация о днях и часах работы;
- lat — широта географической точки, в которой находится заведение;
- lng — долгота географической точки, в которой находится заведение;
- rating — рейтинг заведения по оценкам пользователей в Яндекс Картах (высшая оценка — 5.0);
- price — категория цен в заведении, например «средние», «ниже среднего», «выше среднего» и так далее;
- avg_bill — строка, которая хранит среднюю стоимость заказа в виде диапазона, например:
- «Средний счёт: 1000–1500 ₽»;
- «Цена чашки капучино: 130–220 ₽»;
- «Цена бокала пива: 400–600 ₽» и так далее;
- middle_avg_bill — число с оценкой среднего чека, которое указано только для значений из столбца avg_bill, начинающихся с подстроки «Средний счёт»:
- Если в строке указан ценовой диапазон из двух значений, в столбец войдёт медиана этих двух значений.
- Если в строке указано одно число — цена без диапазона, то в столбец войдёт это число.
- Если значения нет или оно не начинается с подстроки «Средний счёт», то в столбец ничего не войдёт.
- middle_coffee_cup — число с оценкой одной чашки капучино, которое указано только для значений из столбца avg_bill, начинающихся с подстроки «Цена одной чашки капучино»:
- Если в строке указан ценовой диапазон из двух значений, в столбец войдёт медиана этих двух значений.
- Если в строке указано одно число — цена без диапазона, то в столбец войдёт это число.
- Если значения нет или оно не начинается с подстроки «Цена одной чашки капучино», то в столбец ничего не войдёт.
- chain — число, выраженное 0 или 1, которое показывает, является ли заведение сетевым (для маленьких сетей могут встречаться ошибки):
- 0 — заведение не является сетевым
- 1 — заведение является сетевым
- district — административный район, в котором находится заведение, например Центральный административный округ;
- seats — количество посадочных мест.
Последовательность выполнения проекта¶
Загрузите данные и изучите общую информацию¶
- Загрузите данные о заведениях общественного питания Москвы. Путь к файлу:
/datasets/moscow_places.csv - Изучите общую информацию о датасете. Сколько заведений представлено? Что можно сказать о каждом столбце? Значения какого типа они хранят?
Выполните предобработку данных¶
- Изучите, есть ли дубликаты в данных. Поищите пропуски: встречаются ли они, в каких столбцах? Можно ли их обработать или оставить как есть?
- Выполните предобработку данных:
- Создайте столбец street с названиями улиц из столбца с адресом.
- Создайте столбец is_24_7 с обозначением, что заведение работает ежедневно и круглосуточно (24/7):
- логическое значение True — если заведение работает ежедневно и круглосуточно;
- логическое значение False — в противоположном случае.
Анализ данных¶
- Какие категории заведений представлены в данных? Исследуйте количество объектов общественного питания по категориям: рестораны, кофейни, пиццерии, бары и так далее. Постройте визуализации. Ответьте на вопрос о распределении заведений по категориям.
- Исследуйте количество посадочных мест в местах по категориям: рестораны, кофейни, пиццерии, бары и так далее. Постройте визуализации. Проанализируйте результаты и сделайте выводы.
- Рассмотрите и изобразите соотношение сетевых и несетевых заведений в датасете. Каких заведений больше?
- Какие категории заведений чаще являются сетевыми? Исследуйте данные и ответьте на вопрос графиком.
- Сгруппируйте данные по названиям заведений и найдите топ-15 популярных сетей в Москве. Под популярностью понимается количество заведений этой сети в регионе. Постройте подходящую для такой информации визуализацию. Знакомы ли вам эти сети? Есть ли какой-то признак, который их объединяет? К какой категории заведений они относятся?
- Какие административные районы Москвы присутствуют в датасете? Отобразите общее количество заведений и количество заведений каждой категории по районам. Попробуйте проиллюстрировать эту информацию одним графиком.
- Визуализируйте распределение средних рейтингов по категориям заведений. Сильно ли различаются усреднённые рейтинги в разных типах общепита?
- Постройте фоновую картограмму (хороплет) со средним рейтингом заведений каждого района. Границы районов Москвы, которые встречаются в датасете, хранятся в файле
admin_level_geomap.geojson. - Отобразите все заведения датасета на карте с помощью кластеров средствами библиотеки folium.
- Найдите топ-15 улиц по количеству заведений. Постройте график распределения количества заведений и их категорий по этим улицам. Попробуйте проиллюстрировать эту информацию одним графиком.
- Найдите улицы, на которых находится только один объект общепита. Что можно сказать об этих заведениях?
- Значения средних чеков заведений хранятся в столбце middle_avg_bill. Эти числа показывают примерную стоимость заказа в рублях, которая чаще всего выражена диапазоном. Посчитайте медиану этого столбца для каждого района. Используйте это значение в качестве ценового индикатора района. Постройте фоновую картограмму (хороплет) с полученными значениями для каждого района. Проанализируйте цены в центральном административном округе и других. Как удалённость от центра влияет на цены в заведениях?
- Соберите наблюдения по вопросам выше в один общий вывод.
Детализируем исследование: открытие кофейни¶
Основателям фонда «Shut Up and Take My Money» не даёт покоя успех сериала «Друзья». Их мечта — открыть такую же крутую и доступную, как «Central Perk», кофейню в Москве. Будем считать, что заказчики не боятся конкуренции в этой сфере, ведь кофеен в больших городах уже достаточно. Попробуйте определить, осуществима ли мечта клиентов.
- Ответьте на следующие вопросы:
- Сколько всего кофеен в датасете? В каких районах их больше всего, каковы особенности их расположения?
- Есть ли круглосуточные кофейни?
- Какие у кофеен рейтинги? Как они распределяются по районам?
- На какую стоимость чашки капучино стоит ориентироваться при открытии и почему?
- По желанию вы можете расширить список вопросов для исследования, добавив собственные.
- Постройте визуализации. Попробуйте дать рекомендацию для открытия нового заведения. Это творческое задание: здесь нет правильного или неправильного ответа, но ваше решение должно быть чем-то обосновано. Объяснить свою рекомендацию можно текстом с описанием или маркерами на географической карте.
Подготовка презентации¶
Подготовьте презентацию исследования для инвесторов.
Выполнение проекта¶
Загрузка данных и изучение общей информации¶
Загрузим библиотеки, которые будем использовать в ходе выполнения проекта.
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import seaborn as sns
import plotly.express as px
from folium import Map, Choropleth, Marker
from folium.plugins import MarkerCluster
Считаем данные из csv-файла в датафрейм и сохраним в пременную places. Путь к файлу: /datasets/moscow_places.csv
places = pd.read_csv('/datasets/moscow_places.csv')
Зададим функцию для вывода всей информации о таблице.
def df_info(df):
print('\033[1m' + 'Первые 20 строк таблицы:' + '\033[0m')
display(df.head(20))
print()
print('\033[1m' + 'Общая информация о таблице:' + '\033[0m')
print(df.info())
print()
is_na_amt = df.isna().sum()
is_na_percent = round(df.isnull().sum().sort_values()/ len(df)*100, 2)
is_na = pd.concat([is_na_amt, is_na_percent], axis=1)
is_na.columns=(['Количество пропусков', '% пропусков'])
print('\033[1m' + 'Информация о пропусках в таблице:' + '\033[0m')
display(is_na)
print()
print('\033[1m' + 'Количество дубликатов в таблице:' + '\033[0m')
print(df.duplicated().sum())
df_info(places)
Первые 20 строк таблицы:
| name | category | address | district | hours | lat | lng | rating | price | avg_bill | middle_avg_bill | middle_coffee_cup | chain | seats | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | WoWфли | кафе | Москва, улица Дыбенко, 7/1 | Северный административный округ | ежедневно, 10:00–22:00 | 55.878494 | 37.478860 | 5.0 | NaN | NaN | NaN | NaN | 0 | NaN |
| 1 | Четыре комнаты | ресторан | Москва, улица Дыбенко, 36, корп. 1 | Северный административный округ | ежедневно, 10:00–22:00 | 55.875801 | 37.484479 | 4.5 | выше среднего | Средний счёт:1500–1600 ₽ | 1550.0 | NaN | 0 | 4.0 |
| 2 | Хазри | кафе | Москва, Клязьминская улица, 15 | Северный административный округ | пн-чт 11:00–02:00; пт,сб 11:00–05:00; вс 11:00... | 55.889146 | 37.525901 | 4.6 | средние | Средний счёт:от 1000 ₽ | 1000.0 | NaN | 0 | 45.0 |
| 3 | Dormouse Coffee Shop | кофейня | Москва, улица Маршала Федоренко, 12 | Северный административный округ | ежедневно, 09:00–22:00 | 55.881608 | 37.488860 | 5.0 | NaN | Цена чашки капучино:155–185 ₽ | NaN | 170.0 | 0 | NaN |
| 4 | Иль Марко | пиццерия | Москва, Правобережная улица, 1Б | Северный административный округ | ежедневно, 10:00–22:00 | 55.881166 | 37.449357 | 5.0 | средние | Средний счёт:400–600 ₽ | 500.0 | NaN | 1 | 148.0 |
| 5 | Sergio Pizza | пиццерия | Москва, Ижорская улица, вл8Б | Северный административный округ | ежедневно, 10:00–23:00 | 55.888010 | 37.509573 | 4.6 | средние | NaN | NaN | NaN | 0 | NaN |
| 6 | Огни города | бар,паб | Москва, Клязьминская улица, 9, стр. 3 | Северный административный округ | пн 15:00–04:00; вт-вс 15:00–05:00 | 55.890752 | 37.524653 | 4.4 | средние | Средний счёт:199 ₽ | 199.0 | NaN | 0 | 45.0 |
| 7 | Mr. Уголёк | быстрое питание | Москва, Клязьминская улица, 9, стр. 3 | Северный административный округ | пн-чт 10:00–22:00; пт,сб 10:00–23:00; вс 10:00... | 55.890636 | 37.524303 | 4.7 | средние | Средний счёт:200–300 ₽ | 250.0 | NaN | 0 | 45.0 |
| 8 | Donna Maria | ресторан | Москва, Дмитровское шоссе, 107, корп. 4 | Северный административный округ | ежедневно, 10:00–22:00 | 55.880045 | 37.539006 | 4.8 | средние | Средний счёт:от 500 ₽ | 500.0 | NaN | 0 | 79.0 |
| 9 | Готика | кафе | Москва, Ангарская улица, 39 | Северный административный округ | ежедневно, 12:00–00:00 | 55.879038 | 37.524487 | 4.3 | средние | Средний счёт:1000–1200 ₽ | 1100.0 | NaN | 0 | 65.0 |
| 10 | Great Room Bar | бар,паб | Москва, Левобережная улица, 12 | Северный административный округ | ежедневно, круглосуточно | 55.877832 | 37.469171 | 4.5 | средние | Цена бокала пива:250–350 ₽ | NaN | NaN | 0 | 102.0 |
| 11 | Шашлык Шефф | кафе | Москва, улица Маршала Федоренко, 10с1 | Северный административный округ | ежедневно, 10:00–21:00 | 55.881770 | 37.492362 | 4.9 | NaN | NaN | NaN | NaN | 0 | NaN |
| 12 | Заправка | кафе | Москва, МКАД, 80-й километр, 1 | Северный административный округ | вт-сб 09:00–18:00 | 55.899938 | 37.517958 | 4.3 | средние | Средний счёт:330 ₽ | 330.0 | NaN | 0 | NaN |
| 13 | Буханка | булочная | Москва, Базовская улица, 15, корп. 1 | Северный административный округ | ежедневно, 08:00–22:00 | 55.877007 | 37.504980 | 4.8 | NaN | NaN | NaN | NaN | 1 | 180.0 |
| 14 | У Сильвы | бар,паб | Москва, Ангарская улица, 42с1 | Северный административный округ | ежедневно, 13:00–00:00 | 55.885528 | 37.528371 | 4.2 | выше среднего | Средний счёт:1500 ₽ | 1500.0 | NaN | 0 | NaN |
| 15 | Дом обеда | столовая | Москва, улица Бусиновская Горка, 2 | Северный административный округ | пн-пт 08:30–18:30; сб 10:00–20:00 | 55.885890 | 37.493264 | 4.1 | средние | Средний счёт:300–500 ₽ | 400.0 | NaN | 0 | 180.0 |
| 16 | База Стритфуд | кафе | Москва, Базовская улица, 15, корп. 8 | Северный административный округ | ежедневно, 10:00–23:00 | 55.877859 | 37.507754 | 4.2 | средние | Средний счёт:140–350 ₽ | 245.0 | NaN | 0 | NaN |
| 17 | Чайхана Беш-Бармак | ресторан | Москва, Ленинградское шоссе, 71Б, стр. 2 | Северный административный округ | ежедневно, круглосуточно | 55.876908 | 37.449876 | 4.4 | средние | Средний счёт:350–500 ₽ | 425.0 | NaN | 0 | 96.0 |
| 18 | Час-Пик | столовая | Москва, Коровинское шоссе, 30А | Северный административный округ | ежедневно, 09:00–21:00 | 55.884651 | 37.517482 | 4.3 | средние | Средний счёт:200–300 ₽ | 250.0 | NaN | 0 | 25.0 |
| 19 | Пекарня | булочная | Москва, Ижорский проезд, 5 | Северный административный округ | ежедневно, круглосуточно | 55.887969 | 37.515688 | 4.4 | NaN | NaN | NaN | NaN | 1 | NaN |
Общая информация о таблице: <class 'pandas.core.frame.DataFrame'> RangeIndex: 8406 entries, 0 to 8405 Data columns (total 14 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 name 8406 non-null object 1 category 8406 non-null object 2 address 8406 non-null object 3 district 8406 non-null object 4 hours 7870 non-null object 5 lat 8406 non-null float64 6 lng 8406 non-null float64 7 rating 8406 non-null float64 8 price 3315 non-null object 9 avg_bill 3816 non-null object 10 middle_avg_bill 3149 non-null float64 11 middle_coffee_cup 535 non-null float64 12 chain 8406 non-null int64 13 seats 4795 non-null float64 dtypes: float64(6), int64(1), object(7) memory usage: 919.5+ KB None Информация о пропусках в таблице:
| Количество пропусков | % пропусков | |
|---|---|---|
| name | 0 | 0.00 |
| category | 0 | 0.00 |
| address | 0 | 0.00 |
| district | 0 | 0.00 |
| hours | 536 | 6.38 |
| lat | 0 | 0.00 |
| lng | 0 | 0.00 |
| rating | 0 | 0.00 |
| price | 5091 | 60.56 |
| avg_bill | 4590 | 54.60 |
| middle_avg_bill | 5257 | 62.54 |
| middle_coffee_cup | 7871 | 93.64 |
| chain | 0 | 0.00 |
| seats | 3611 | 42.96 |
Количество дубликатов в таблице:
0
В датасете представлена информация о 8406 заведениях. Столбцы с данными о названии, категории заведения, адресе, районе, часах работы, категории цен и средней стоимости заказа имеет тип данных object, с информацией о широте, долготе, рейтинге, среднем чеке, средней цене чашки капучино, количестве мест имеет тип данных float, с информацией о принадлежности к сети - тип данных int.
Предобработка данных¶
Датасет не явных содержит дубликатов. Но содержит пропуски в столбцах с часами работы, уровнем цен, среднем счетом, средней ценой чашки капучино, количеством мест. При чем пропусков достаточно много, удалить их не представляетс возможным, по этой причине оставляем их в данных.
Создадим столбец street с названиями улиц из столбца с адресом.
places['street'] = places['address'].str.split(',').str[1].str.strip()
Создадим столбец is_24_7 с обозначением, что заведение работает ежедневно и круглосуточно (24/7), который будет содержать логическое значение True, если заведение работает ежедневно и круглосуточно, или логическое значение False в противоположном случае.
places['is_24_7'] = places['hours'].str.contains(r'\ежедневно, круглосуточно')
Проверим данные после всех изменений.
df_info(places)
Первые 20 строк таблицы:
| name | category | address | district | hours | lat | lng | rating | price | avg_bill | middle_avg_bill | middle_coffee_cup | chain | seats | street | is_24_7 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | WoWфли | кафе | Москва, улица Дыбенко, 7/1 | Северный административный округ | ежедневно, 10:00–22:00 | 55.878494 | 37.478860 | 5.0 | NaN | NaN | NaN | NaN | 0 | NaN | улица Дыбенко | False |
| 1 | Четыре комнаты | ресторан | Москва, улица Дыбенко, 36, корп. 1 | Северный административный округ | ежедневно, 10:00–22:00 | 55.875801 | 37.484479 | 4.5 | выше среднего | Средний счёт:1500–1600 ₽ | 1550.0 | NaN | 0 | 4.0 | улица Дыбенко | False |
| 2 | Хазри | кафе | Москва, Клязьминская улица, 15 | Северный административный округ | пн-чт 11:00–02:00; пт,сб 11:00–05:00; вс 11:00... | 55.889146 | 37.525901 | 4.6 | средние | Средний счёт:от 1000 ₽ | 1000.0 | NaN | 0 | 45.0 | Клязьминская улица | False |
| 3 | Dormouse Coffee Shop | кофейня | Москва, улица Маршала Федоренко, 12 | Северный административный округ | ежедневно, 09:00–22:00 | 55.881608 | 37.488860 | 5.0 | NaN | Цена чашки капучино:155–185 ₽ | NaN | 170.0 | 0 | NaN | улица Маршала Федоренко | False |
| 4 | Иль Марко | пиццерия | Москва, Правобережная улица, 1Б | Северный административный округ | ежедневно, 10:00–22:00 | 55.881166 | 37.449357 | 5.0 | средние | Средний счёт:400–600 ₽ | 500.0 | NaN | 1 | 148.0 | Правобережная улица | False |
| 5 | Sergio Pizza | пиццерия | Москва, Ижорская улица, вл8Б | Северный административный округ | ежедневно, 10:00–23:00 | 55.888010 | 37.509573 | 4.6 | средние | NaN | NaN | NaN | 0 | NaN | Ижорская улица | False |
| 6 | Огни города | бар,паб | Москва, Клязьминская улица, 9, стр. 3 | Северный административный округ | пн 15:00–04:00; вт-вс 15:00–05:00 | 55.890752 | 37.524653 | 4.4 | средние | Средний счёт:199 ₽ | 199.0 | NaN | 0 | 45.0 | Клязьминская улица | False |
| 7 | Mr. Уголёк | быстрое питание | Москва, Клязьминская улица, 9, стр. 3 | Северный административный округ | пн-чт 10:00–22:00; пт,сб 10:00–23:00; вс 10:00... | 55.890636 | 37.524303 | 4.7 | средние | Средний счёт:200–300 ₽ | 250.0 | NaN | 0 | 45.0 | Клязьминская улица | False |
| 8 | Donna Maria | ресторан | Москва, Дмитровское шоссе, 107, корп. 4 | Северный административный округ | ежедневно, 10:00–22:00 | 55.880045 | 37.539006 | 4.8 | средние | Средний счёт:от 500 ₽ | 500.0 | NaN | 0 | 79.0 | Дмитровское шоссе | False |
| 9 | Готика | кафе | Москва, Ангарская улица, 39 | Северный административный округ | ежедневно, 12:00–00:00 | 55.879038 | 37.524487 | 4.3 | средние | Средний счёт:1000–1200 ₽ | 1100.0 | NaN | 0 | 65.0 | Ангарская улица | False |
| 10 | Great Room Bar | бар,паб | Москва, Левобережная улица, 12 | Северный административный округ | ежедневно, круглосуточно | 55.877832 | 37.469171 | 4.5 | средние | Цена бокала пива:250–350 ₽ | NaN | NaN | 0 | 102.0 | Левобережная улица | True |
| 11 | Шашлык Шефф | кафе | Москва, улица Маршала Федоренко, 10с1 | Северный административный округ | ежедневно, 10:00–21:00 | 55.881770 | 37.492362 | 4.9 | NaN | NaN | NaN | NaN | 0 | NaN | улица Маршала Федоренко | False |
| 12 | Заправка | кафе | Москва, МКАД, 80-й километр, 1 | Северный административный округ | вт-сб 09:00–18:00 | 55.899938 | 37.517958 | 4.3 | средние | Средний счёт:330 ₽ | 330.0 | NaN | 0 | NaN | МКАД | False |
| 13 | Буханка | булочная | Москва, Базовская улица, 15, корп. 1 | Северный административный округ | ежедневно, 08:00–22:00 | 55.877007 | 37.504980 | 4.8 | NaN | NaN | NaN | NaN | 1 | 180.0 | Базовская улица | False |
| 14 | У Сильвы | бар,паб | Москва, Ангарская улица, 42с1 | Северный административный округ | ежедневно, 13:00–00:00 | 55.885528 | 37.528371 | 4.2 | выше среднего | Средний счёт:1500 ₽ | 1500.0 | NaN | 0 | NaN | Ангарская улица | False |
| 15 | Дом обеда | столовая | Москва, улица Бусиновская Горка, 2 | Северный административный округ | пн-пт 08:30–18:30; сб 10:00–20:00 | 55.885890 | 37.493264 | 4.1 | средние | Средний счёт:300–500 ₽ | 400.0 | NaN | 0 | 180.0 | улица Бусиновская Горка | False |
| 16 | База Стритфуд | кафе | Москва, Базовская улица, 15, корп. 8 | Северный административный округ | ежедневно, 10:00–23:00 | 55.877859 | 37.507754 | 4.2 | средние | Средний счёт:140–350 ₽ | 245.0 | NaN | 0 | NaN | Базовская улица | False |
| 17 | Чайхана Беш-Бармак | ресторан | Москва, Ленинградское шоссе, 71Б, стр. 2 | Северный административный округ | ежедневно, круглосуточно | 55.876908 | 37.449876 | 4.4 | средние | Средний счёт:350–500 ₽ | 425.0 | NaN | 0 | 96.0 | Ленинградское шоссе | True |
| 18 | Час-Пик | столовая | Москва, Коровинское шоссе, 30А | Северный административный округ | ежедневно, 09:00–21:00 | 55.884651 | 37.517482 | 4.3 | средние | Средний счёт:200–300 ₽ | 250.0 | NaN | 0 | 25.0 | Коровинское шоссе | False |
| 19 | Пекарня | булочная | Москва, Ижорский проезд, 5 | Северный административный округ | ежедневно, круглосуточно | 55.887969 | 37.515688 | 4.4 | NaN | NaN | NaN | NaN | 1 | NaN | Ижорский проезд | True |
Общая информация о таблице: <class 'pandas.core.frame.DataFrame'> RangeIndex: 8406 entries, 0 to 8405 Data columns (total 16 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 name 8406 non-null object 1 category 8406 non-null object 2 address 8406 non-null object 3 district 8406 non-null object 4 hours 7870 non-null object 5 lat 8406 non-null float64 6 lng 8406 non-null float64 7 rating 8406 non-null float64 8 price 3315 non-null object 9 avg_bill 3816 non-null object 10 middle_avg_bill 3149 non-null float64 11 middle_coffee_cup 535 non-null float64 12 chain 8406 non-null int64 13 seats 4795 non-null float64 14 street 8406 non-null object 15 is_24_7 7870 non-null object dtypes: float64(6), int64(1), object(9) memory usage: 1.0+ MB None Информация о пропусках в таблице:
| Количество пропусков | % пропусков | |
|---|---|---|
| name | 0 | 0.00 |
| category | 0 | 0.00 |
| address | 0 | 0.00 |
| district | 0 | 0.00 |
| hours | 536 | 6.38 |
| lat | 0 | 0.00 |
| lng | 0 | 0.00 |
| rating | 0 | 0.00 |
| price | 5091 | 60.56 |
| avg_bill | 4590 | 54.60 |
| middle_avg_bill | 5257 | 62.54 |
| middle_coffee_cup | 7871 | 93.64 |
| chain | 0 | 0.00 |
| seats | 3611 | 42.96 |
| street | 0 | 0.00 |
| is_24_7 | 536 | 6.38 |
Количество дубликатов в таблице:
0
Прверим датафрейм на наличие неявных дубликато, заведений с одинаковым название м по одинаковому адресу.
places['name'] = places['name'].str.lower()
places['address'] = places['address'].str.lower()
places_duplicates = places[places.duplicated(['name', 'address'])]
places_duplicates
| name | category | address | district | hours | lat | lng | rating | price | avg_bill | middle_avg_bill | middle_coffee_cup | chain | seats | street | is_24_7 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 215 | кафе | кафе | москва, парк ангарские пруды | Северный административный округ | ежедневно, 10:00–22:00 | 55.881438 | 37.531848 | 3.2 | NaN | NaN | NaN | NaN | 0 | NaN | парк Ангарские пруды | False |
| 1511 | more poke | ресторан | москва, волоколамское шоссе, 11, стр. 2 | Северный административный округ | пн-чт 09:00–18:00; пт,сб 09:00–21:00; вс 09:00... | 55.806307 | 37.497566 | 4.2 | NaN | NaN | NaN | NaN | 1 | 188.0 | Волоколамское шоссе | False |
| 2420 | раковарня клешни и хвосты | бар,паб | москва, проспект мира, 118 | Северо-Восточный административный округ | пн-чт 12:00–00:00; пт,сб 12:00–01:00; вс 12:00... | 55.810677 | 37.638379 | 4.4 | NaN | NaN | NaN | NaN | 1 | 150.0 | проспект Мира | False |
| 3109 | хлеб да выпечка | кафе | москва, ярцевская улица, 19 | Западный административный округ | NaN | 55.738449 | 37.410937 | 4.1 | NaN | NaN | NaN | NaN | 0 | 276.0 | Ярцевская улица | NaN |
Убедимся, что эти заведения действительно являются дубликатами.
places.query('name == "кафе" & address == "москва, парк ангарские пруды"')
| name | category | address | district | hours | lat | lng | rating | price | avg_bill | middle_avg_bill | middle_coffee_cup | chain | seats | street | is_24_7 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 189 | кафе | кафе | москва, парк ангарские пруды | Северный административный округ | ежедневно, 09:00–23:00 | 55.880327 | 37.530786 | 3.2 | NaN | NaN | NaN | NaN | 0 | NaN | парк Ангарские Пруды | False |
| 215 | кафе | кафе | москва, парк ангарские пруды | Северный административный округ | ежедневно, 10:00–22:00 | 55.881438 | 37.531848 | 3.2 | NaN | NaN | NaN | NaN | 0 | NaN | парк Ангарские пруды | False |
places.query('name == "more poke" & address == "москва, волоколамское шоссе, 11, стр. 2"')
| name | category | address | district | hours | lat | lng | rating | price | avg_bill | middle_avg_bill | middle_coffee_cup | chain | seats | street | is_24_7 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1430 | more poke | ресторан | москва, волоколамское шоссе, 11, стр. 2 | Северный административный округ | ежедневно, 09:00–21:00 | 55.806307 | 37.497566 | 4.2 | NaN | NaN | NaN | NaN | 0 | 188.0 | Волоколамское шоссе | False |
| 1511 | more poke | ресторан | москва, волоколамское шоссе, 11, стр. 2 | Северный административный округ | пн-чт 09:00–18:00; пт,сб 09:00–21:00; вс 09:00... | 55.806307 | 37.497566 | 4.2 | NaN | NaN | NaN | NaN | 1 | 188.0 | Волоколамское шоссе | False |
places.query('name == "раковарня клешни и хвосты" & address == "москва, проспект мира, 118"')
| name | category | address | district | hours | lat | lng | rating | price | avg_bill | middle_avg_bill | middle_coffee_cup | chain | seats | street | is_24_7 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2211 | раковарня клешни и хвосты | ресторан | москва, проспект мира, 118 | Северо-Восточный административный округ | ежедневно, 12:00–00:00 | 55.810553 | 37.638161 | 4.4 | NaN | NaN | NaN | NaN | 0 | 150.0 | проспект Мира | False |
| 2420 | раковарня клешни и хвосты | бар,паб | москва, проспект мира, 118 | Северо-Восточный административный округ | пн-чт 12:00–00:00; пт,сб 12:00–01:00; вс 12:00... | 55.810677 | 37.638379 | 4.4 | NaN | NaN | NaN | NaN | 1 | 150.0 | проспект Мира | False |
places.query('name == "хлеб да выпечка" & address == "москва, ярцевская улица, 19"')
| name | category | address | district | hours | lat | lng | rating | price | avg_bill | middle_avg_bill | middle_coffee_cup | chain | seats | street | is_24_7 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 3091 | хлеб да выпечка | булочная | москва, ярцевская улица, 19 | Западный административный округ | ежедневно, 09:00–22:00 | 55.738886 | 37.411648 | 4.1 | NaN | NaN | NaN | NaN | 1 | 276.0 | Ярцевская улица | False |
| 3109 | хлеб да выпечка | кафе | москва, ярцевская улица, 19 | Западный административный округ | NaN | 55.738449 | 37.410937 | 4.1 | NaN | NaN | NaN | NaN | 0 | 276.0 | Ярцевская улица | NaN |
Заведения из списка places_duplicates действительно являются дубликатами. У некоторых заведений незначительно отличаются координаты, это могло произойти из-за того, что определение координат происходило в разгое время, при разных условиях, разными приборами. Удалим дубликаты из датафрейма.
places = places.drop(index=[215, 1511, 2420, 3109]).reset_index(drop=True)
Проверим датафрейм после изменений.
df_info(places)
Первые 20 строк таблицы:
| name | category | address | district | hours | lat | lng | rating | price | avg_bill | middle_avg_bill | middle_coffee_cup | chain | seats | street | is_24_7 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | wowфли | кафе | москва, улица дыбенко, 7/1 | Северный административный округ | ежедневно, 10:00–22:00 | 55.878494 | 37.478860 | 5.0 | NaN | NaN | NaN | NaN | 0 | NaN | улица Дыбенко | False |
| 1 | четыре комнаты | ресторан | москва, улица дыбенко, 36, корп. 1 | Северный административный округ | ежедневно, 10:00–22:00 | 55.875801 | 37.484479 | 4.5 | выше среднего | Средний счёт:1500–1600 ₽ | 1550.0 | NaN | 0 | 4.0 | улица Дыбенко | False |
| 2 | хазри | кафе | москва, клязьминская улица, 15 | Северный административный округ | пн-чт 11:00–02:00; пт,сб 11:00–05:00; вс 11:00... | 55.889146 | 37.525901 | 4.6 | средние | Средний счёт:от 1000 ₽ | 1000.0 | NaN | 0 | 45.0 | Клязьминская улица | False |
| 3 | dormouse coffee shop | кофейня | москва, улица маршала федоренко, 12 | Северный административный округ | ежедневно, 09:00–22:00 | 55.881608 | 37.488860 | 5.0 | NaN | Цена чашки капучино:155–185 ₽ | NaN | 170.0 | 0 | NaN | улица Маршала Федоренко | False |
| 4 | иль марко | пиццерия | москва, правобережная улица, 1б | Северный административный округ | ежедневно, 10:00–22:00 | 55.881166 | 37.449357 | 5.0 | средние | Средний счёт:400–600 ₽ | 500.0 | NaN | 1 | 148.0 | Правобережная улица | False |
| 5 | sergio pizza | пиццерия | москва, ижорская улица, вл8б | Северный административный округ | ежедневно, 10:00–23:00 | 55.888010 | 37.509573 | 4.6 | средние | NaN | NaN | NaN | 0 | NaN | Ижорская улица | False |
| 6 | огни города | бар,паб | москва, клязьминская улица, 9, стр. 3 | Северный административный округ | пн 15:00–04:00; вт-вс 15:00–05:00 | 55.890752 | 37.524653 | 4.4 | средние | Средний счёт:199 ₽ | 199.0 | NaN | 0 | 45.0 | Клязьминская улица | False |
| 7 | mr. уголёк | быстрое питание | москва, клязьминская улица, 9, стр. 3 | Северный административный округ | пн-чт 10:00–22:00; пт,сб 10:00–23:00; вс 10:00... | 55.890636 | 37.524303 | 4.7 | средние | Средний счёт:200–300 ₽ | 250.0 | NaN | 0 | 45.0 | Клязьминская улица | False |
| 8 | donna maria | ресторан | москва, дмитровское шоссе, 107, корп. 4 | Северный административный округ | ежедневно, 10:00–22:00 | 55.880045 | 37.539006 | 4.8 | средние | Средний счёт:от 500 ₽ | 500.0 | NaN | 0 | 79.0 | Дмитровское шоссе | False |
| 9 | готика | кафе | москва, ангарская улица, 39 | Северный административный округ | ежедневно, 12:00–00:00 | 55.879038 | 37.524487 | 4.3 | средние | Средний счёт:1000–1200 ₽ | 1100.0 | NaN | 0 | 65.0 | Ангарская улица | False |
| 10 | great room bar | бар,паб | москва, левобережная улица, 12 | Северный административный округ | ежедневно, круглосуточно | 55.877832 | 37.469171 | 4.5 | средние | Цена бокала пива:250–350 ₽ | NaN | NaN | 0 | 102.0 | Левобережная улица | True |
| 11 | шашлык шефф | кафе | москва, улица маршала федоренко, 10с1 | Северный административный округ | ежедневно, 10:00–21:00 | 55.881770 | 37.492362 | 4.9 | NaN | NaN | NaN | NaN | 0 | NaN | улица Маршала Федоренко | False |
| 12 | заправка | кафе | москва, мкад, 80-й километр, 1 | Северный административный округ | вт-сб 09:00–18:00 | 55.899938 | 37.517958 | 4.3 | средние | Средний счёт:330 ₽ | 330.0 | NaN | 0 | NaN | МКАД | False |
| 13 | буханка | булочная | москва, базовская улица, 15, корп. 1 | Северный административный округ | ежедневно, 08:00–22:00 | 55.877007 | 37.504980 | 4.8 | NaN | NaN | NaN | NaN | 1 | 180.0 | Базовская улица | False |
| 14 | у сильвы | бар,паб | москва, ангарская улица, 42с1 | Северный административный округ | ежедневно, 13:00–00:00 | 55.885528 | 37.528371 | 4.2 | выше среднего | Средний счёт:1500 ₽ | 1500.0 | NaN | 0 | NaN | Ангарская улица | False |
| 15 | дом обеда | столовая | москва, улица бусиновская горка, 2 | Северный административный округ | пн-пт 08:30–18:30; сб 10:00–20:00 | 55.885890 | 37.493264 | 4.1 | средние | Средний счёт:300–500 ₽ | 400.0 | NaN | 0 | 180.0 | улица Бусиновская Горка | False |
| 16 | база стритфуд | кафе | москва, базовская улица, 15, корп. 8 | Северный административный округ | ежедневно, 10:00–23:00 | 55.877859 | 37.507754 | 4.2 | средние | Средний счёт:140–350 ₽ | 245.0 | NaN | 0 | NaN | Базовская улица | False |
| 17 | чайхана беш-бармак | ресторан | москва, ленинградское шоссе, 71б, стр. 2 | Северный административный округ | ежедневно, круглосуточно | 55.876908 | 37.449876 | 4.4 | средние | Средний счёт:350–500 ₽ | 425.0 | NaN | 0 | 96.0 | Ленинградское шоссе | True |
| 18 | час-пик | столовая | москва, коровинское шоссе, 30а | Северный административный округ | ежедневно, 09:00–21:00 | 55.884651 | 37.517482 | 4.3 | средние | Средний счёт:200–300 ₽ | 250.0 | NaN | 0 | 25.0 | Коровинское шоссе | False |
| 19 | пекарня | булочная | москва, ижорский проезд, 5 | Северный административный округ | ежедневно, круглосуточно | 55.887969 | 37.515688 | 4.4 | NaN | NaN | NaN | NaN | 1 | NaN | Ижорский проезд | True |
Общая информация о таблице: <class 'pandas.core.frame.DataFrame'> RangeIndex: 8402 entries, 0 to 8401 Data columns (total 16 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 name 8402 non-null object 1 category 8402 non-null object 2 address 8402 non-null object 3 district 8402 non-null object 4 hours 7867 non-null object 5 lat 8402 non-null float64 6 lng 8402 non-null float64 7 rating 8402 non-null float64 8 price 3315 non-null object 9 avg_bill 3816 non-null object 10 middle_avg_bill 3149 non-null float64 11 middle_coffee_cup 535 non-null float64 12 chain 8402 non-null int64 13 seats 4792 non-null float64 14 street 8402 non-null object 15 is_24_7 7867 non-null object dtypes: float64(6), int64(1), object(9) memory usage: 1.0+ MB None Информация о пропусках в таблице:
| Количество пропусков | % пропусков | |
|---|---|---|
| name | 0 | 0.00 |
| category | 0 | 0.00 |
| address | 0 | 0.00 |
| district | 0 | 0.00 |
| hours | 535 | 6.37 |
| lat | 0 | 0.00 |
| lng | 0 | 0.00 |
| rating | 0 | 0.00 |
| price | 5087 | 60.55 |
| avg_bill | 4586 | 54.58 |
| middle_avg_bill | 5253 | 62.52 |
| middle_coffee_cup | 7867 | 93.63 |
| chain | 0 | 0.00 |
| seats | 3610 | 42.97 |
| street | 0 | 0.00 |
| is_24_7 | 535 | 6.37 |
Количество дубликатов в таблице:
0
Итоговый датафрейм содержит информацию о 8402 заведенияхобщественного питания Москвы.
Анализ данных¶
Исследуем количество объектов общественного питания по категориям.
places_by_category = places.pivot_table(index='category', values='name', aggfunc='count').sort_values(by='name', ascending=False).reset_index()
places_by_category.columns = (['category', 'places_amt'])
places_by_category['places_percent'] = round((places_by_category['places_amt'] / places_by_category['places_amt'].sum()) * 100, 2)
places_by_category
| category | places_amt | places_percent | |
|---|---|---|---|
| 0 | кафе | 2376 | 28.28 |
| 1 | ресторан | 2042 | 24.30 |
| 2 | кофейня | 1413 | 16.82 |
| 3 | бар,паб | 764 | 9.09 |
| 4 | пиццерия | 633 | 7.53 |
| 5 | быстрое питание | 603 | 7.18 |
| 6 | столовая | 315 | 3.75 |
| 7 | булочная | 256 | 3.05 |
print('Всего объектов общественного питания в Москве', places_by_category['places_amt'].sum())
Всего объектов общественного питания в Москве 8402
Построим визуализацию.
plt.figure(figsize=(15, 9))
sns.set(palette='bright', style='darkgrid')
ax = sns.barplot(data=places_by_category, x='places_amt', y='category', hue=None)
ax.set(xlabel='Количество объектов', ylabel='Категория заведения', title='Количество объектов по категориям');
Всего в Москве 8402 объекта общественного питания. Они распределены по семи категориям: кафе, рестораны, кофейни, бары или пабы, пиццерии, быстрое питание, столовые, булочные. Более половины всех объектов приходится на категории кафе и рестораны - 2376 (28,28%) и 2042 (24,30%) соответственно. Меньше всего объектов в категориях столовая и булочная - 315 (3,75%) и 256 (3,05%) соответственно.
Исследуем количество посадочных мест в местах по категориям. Постройте визуализации. Проанализируйте результаты и сделайте выводы.
seats_by_category = places.pivot_table(index='category', values='seats', aggfunc='sum').sort_values(by='seats', ascending=False).reset_index()
seats_by_category.columns = (['category', 'seats_amt'])
seats_by_category
| category | seats_amt | |
|---|---|---|
| 0 | ресторан | 154681.0 |
| 1 | кафе | 118494.0 |
| 2 | кофейня | 83511.0 |
| 3 | бар,паб | 58131.0 |
| 4 | пиццерия | 40350.0 |
| 5 | быстрое питание | 34513.0 |
| 6 | столовая | 16359.0 |
| 7 | булочная | 13229.0 |
Построим визуализацию.
plt.figure(figsize=(15, 9))
sns.set(palette='bright', style='darkgrid')
ax = sns.barplot(data=seats_by_category, x='seats_amt', y='category', hue=None)
ax.set(xlabel='Количество посадочных мест', ylabel='Категория заведения', title='Количество посадочных мест по категориям');
Ожидаемо больше всего мест в ресторанах и кафе - 154681 и 118494 соответствнно, а меньше всего в булочных - 13229. Стоит отметить, что в данных по количеству посадочных мест есть пропуски, это могло оказать влияние на итоговый результат.
Рассмотрим соотношение сетевых и несетевых заведений в датасете.
places_is_chain = places.pivot_table(index='chain', values='name', aggfunc='count').reset_index(drop=True)
places_is_chain['chain'] = (['not_chain', 'is_chain'])
places_is_chain = places_is_chain[['chain', 'name']]
places_is_chain.columns = (['chain', 'places_amt'])
places_is_chain
| chain | places_amt | |
|---|---|---|
| 0 | not_chain | 5199 |
| 1 | is_chain | 3203 |
Построим визуализацию.
plt.figure(figsize=(10, 10))
plt.title('Соотношение сетевых и несетевых заведений', fontweight='bold')
plt.pie(places_is_chain['places_amt'], labels=places_is_chain['chain'], autopct='%.0f%%', colors=sns.color_palette('Set2'));
Несетевых заведений больше, 5199 (62%), по отношению к сетевым - 3203 (38%).
Исследуем, какие категории заведений чаще являются сетевыми. Для этого посчитаем долю сетевых заведений от общего количества заведений в категории.
places_categories_by_chain = places.pivot_table(index='category', columns='chain',values='name', aggfunc='count')
places_categories_by_chain.columns = (['not_chain', 'is_chain'])
places_categories_by_chain = places_categories_by_chain.reset_index()
places_categories_by_chain['is_chain_percent'] = round((places_categories_by_chain['is_chain'] /
(places_categories_by_chain['not_chain'] +
places_categories_by_chain['is_chain'])) * 100, 2)
places_categories_by_chain = places_categories_by_chain.sort_values(by='is_chain_percent')
places_categories_by_chain
| category | not_chain | is_chain | is_chain_percent | |
|---|---|---|---|---|
| 0 | бар,паб | 596 | 168 | 21.99 |
| 7 | столовая | 227 | 88 | 27.94 |
| 3 | кафе | 1597 | 779 | 32.79 |
| 6 | ресторан | 1313 | 729 | 35.70 |
| 2 | быстрое питание | 371 | 232 | 38.47 |
| 4 | кофейня | 693 | 720 | 50.96 |
| 5 | пиццерия | 303 | 330 | 52.13 |
| 1 | булочная | 99 | 157 | 61.33 |
Построим визуализацию.
fig = px.bar(places_categories_by_chain,
x='is_chain_percent',
y ='category',
orientation='h',
labels={
'category': 'Категория заведения',
'is_chain_percent': 'Процент сетевых сетевых заведений от общего количества заведений в категории'},
title='Доля сетевых заведений от общего количества заведений в категории')
fig.show()
Больше половины заведений в каждой из категорий булочная, пиццерия и кофейня являются сетевыми - 61,33%, 52,13% и 50,96% соответственно. Меньше всего сетевых заведений в категории бар,паб - 21,99%.
Сгруппируйем данные по названиям заведений и найдием топ-15 популярных сетей в Москве.
top_chain_places = places.query('chain == 1').groupby('name')['name'].count().sort_values().tail(15)
top_chain_places
name му-му 27 буханка 32 cofefest 32 чайхана 37 теремок 38 кулинарная лавка братьев караваевых 39 кофепорт 42 хинкальная 44 prime 50 cofix 65 яндекс лавка 69 one price coffee 71 додо пицца 74 домино'с пицца 76 шоколадница 120 Name: name, dtype: int64
Построим визуализацию.
fig = px.bar(top_chain_places,
orientation='h',
labels={'index': 'Название сети','value': 'Количество заведений'},
title='Количество заведений в топ-15 сетей общественного питания')
fig.show()
В топ-15 самых популярных сетей в Москве больше всего заведений категорий кафе, пиццерии, кофейни.
Изучим, какие административные районы Москвы присутствуют в датасете. Найдем количество заведений каждой категории по районам и общее количество заведений.
places_by_district = places.pivot_table(index='district', columns='category', values='name', aggfunc='count')
places_by_district['всего_заведений'] = places_by_district.sum(axis=1)
places_by_district = places_by_district.sort_values(by='всего_заведений').reset_index()
places_by_district
| category | district | бар,паб | булочная | быстрое питание | кафе | кофейня | пиццерия | ресторан | столовая | всего_заведений |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Северо-Западный административный округ | 23 | 12 | 30 | 115 | 62 | 40 | 109 | 18 | 409 |
| 1 | Юго-Западный административный округ | 38 | 27 | 61 | 238 | 96 | 64 | 168 | 17 | 709 |
| 2 | Юго-Восточный административный округ | 38 | 13 | 67 | 282 | 89 | 55 | 145 | 25 | 714 |
| 3 | Восточный административный округ | 53 | 25 | 71 | 272 | 105 | 72 | 160 | 40 | 798 |
| 4 | Западный административный округ | 50 | 37 | 62 | 238 | 150 | 71 | 218 | 24 | 850 |
| 5 | Северо-Восточный административный округ | 62 | 28 | 82 | 269 | 159 | 68 | 182 | 40 | 890 |
| 6 | Южный административный округ | 68 | 25 | 85 | 264 | 131 | 73 | 202 | 44 | 892 |
| 7 | Северный административный округ | 68 | 39 | 58 | 234 | 193 | 77 | 188 | 41 | 898 |
| 8 | Центральный административный округ | 364 | 50 | 87 | 464 | 428 | 113 | 670 | 66 | 2242 |
В датасете присутствуют все районы Москвы, кроме Зеленоградского, Новомосковского и Троицкого.
Построим визуализацию.
fig = px.bar(places_by_district,
x=['бар,паб', 'булочная', 'быстрое питание', 'кафе', 'кофейня', 'пиццерия', 'ресторан', 'столовая'],
y='district',
orientation='h',
labels={
'district': 'Район',
'value': 'Количество заведений',
'variable': 'Категория заведения'
},
title='Распределение заведений по категориям и по районам')
fig.show()
ЦАО лидирует как по общему количеству заведений (2242), так и по количеству заведений в каждой из категорий. Меньше всего заведений в СЗАО - 409.
Визуализируем распределение средних рейтингов по категориям заведений.
plt.figure(figsize=(15, 9))
sns.boxplot(x='category', y='rating', data=places, order=places.groupby('category')['rating'].mean().sort_values().index,
palette='Set2')
plt.xlabel('Категория заведения')
plt.ylabel('Рейтинг заведения')
plt.title('Распределение средних рейтингов по категориям заведений');
Средние рейтинги мало отличаются, для каждой категории средний рейтинг находятся между 4 и 4,5 баллами.
Построим фоновую картограмму (хороплет) со средним рейтингом заведений каждого района.
Для каждого округа посчитаем средний рейтинг заведений.
places_rating = places.groupby('district', as_index=False)['rating'].agg('mean').sort_values(by='rating', ascending=False)
places_rating
| district | rating | |
|---|---|---|
| 5 | Центральный административный округ | 4.377520 |
| 2 | Северный административный округ | 4.240980 |
| 4 | Северо-Западный административный округ | 4.208802 |
| 8 | Южный административный округ | 4.184417 |
| 1 | Западный административный округ | 4.181647 |
| 0 | Восточный административный округ | 4.174185 |
| 7 | Юго-Западный административный округ | 4.172920 |
| 3 | Северо-Восточный административный округ | 4.147978 |
| 6 | Юго-Восточный административный округ | 4.101120 |
Загрузим JSON-файл с границами округов Москвы.
state_geo = '/datasets/admin_level_geomap.geojson'
Зададим координаты центра Москвы.
moscow_lat = 55.751244
moscow_lng = 37.618423
Создадим карту Москвы.
m = Map(location=[moscow_lat, moscow_lng], zoom_start=10, tiles='Cartodb Positron')
Создадим хороплет с помощью конструктора Choropleth и добавим его на карту.
Choropleth(
geo_data=state_geo,
data=places_rating,
columns=['district', 'rating'],
key_on='feature.name',
fill_color='Blues',
fill_opacity=0.8,
legend_name='Средний рейтинг заведений по районам',
).add_to(m)
m
Наибольший рейтинг у заведений в ЦАО - 4,4 балла, а наименьший у заведений в ЮВАО - 4,1 балла.
Отобразим все заведения датасета на карте с помощью кластеров средствами библиотеки folium.
Создадим новую карту Москвы.
m1 = Map(location=[moscow_lat, moscow_lng], zoom_start=10, tiles='Cartodb Positron')
Создадим пустой кластер, добавим его на карту.
marker_cluster = MarkerCluster().add_to(m1)
Напишем функцию, которая принимает строку датафрейма, создаёт маркер в текущей точке и добавляет его в кластер marker_cluster.
def create_clusters(row):
Marker(
[row['lat'], row['lng']],
popup=f"{row['name']} {row['rating']}",
).add_to(marker_cluster)
Применим функцию create_clusters() к каждой строке датафрейма.
places.apply(create_clusters, axis=1)
0 None
1 None
2 None
3 None
4 None
...
8397 None
8398 None
8399 None
8400 None
8401 None
Length: 8402, dtype: object
Выведем карту.
m1
Найдем топ-15 улиц по количеству заведений. Постройте график распределения количества заведений и их категорий по этим улицам. Попробуйте проиллюстрировать эту информацию одним графиком.
top_streets = places.groupby('street', as_index=False)['name'].agg('count').\
sort_values(by='name').reset_index(drop=True)
top_streets.columns = ('street', 'places_amt')
top15_streets = top_streets.tail(15)
top15_streets
| street | places_amt | |
|---|---|---|
| 1433 | Пятницкая улица | 48 |
| 1434 | улица Миклухо-Маклая | 49 |
| 1435 | Кутузовский проспект | 54 |
| 1436 | улица Вавилова | 55 |
| 1437 | Люблинская улица | 60 |
| 1438 | МКАД | 65 |
| 1439 | Ленинградское шоссе | 70 |
| 1440 | Варшавское шоссе | 76 |
| 1441 | Каширское шоссе | 77 |
| 1442 | Дмитровское шоссе | 88 |
| 1443 | Ленинградский проспект | 95 |
| 1444 | Ленинский проспект | 107 |
| 1445 | проспект Вернадского | 108 |
| 1446 | Профсоюзная улица | 122 |
| 1447 | проспект Мира | 183 |
Составим список топ-15 улиц по количеству заведений.
top_streets_list = top15_streets['street']
Построим график распределения количества заведений и их категорий по этим улицам.
places_by_street = places.query('street in @top_streets_list').pivot_table(index='street', columns='category', values='name', aggfunc='count')
places_by_street['всего_заведений'] = places_by_street.sum(axis=1)
places_by_street = places_by_street.sort_values(by='всего_заведений').reset_index()
places_by_street
| category | street | бар,паб | булочная | быстрое питание | кафе | кофейня | пиццерия | ресторан | столовая | всего_заведений |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Пятницкая улица | 9.0 | 3.0 | 2.0 | 7.0 | 6.0 | 3.0 | 18.0 | NaN | 48.0 |
| 1 | улица Миклухо-Маклая | 3.0 | NaN | 4.0 | 21.0 | 4.0 | 2.0 | 15.0 | NaN | 49.0 |
| 2 | Кутузовский проспект | 2.0 | 1.0 | 2.0 | 14.0 | 13.0 | 3.0 | 16.0 | 3.0 | 54.0 |
| 3 | улица Вавилова | 2.0 | 2.0 | 11.0 | 15.0 | 10.0 | 3.0 | 12.0 | NaN | 55.0 |
| 4 | Люблинская улица | 5.0 | NaN | 5.0 | 26.0 | 11.0 | 1.0 | 10.0 | 2.0 | 60.0 |
| 5 | МКАД | 1.0 | NaN | 9.0 | 45.0 | 4.0 | NaN | 5.0 | 1.0 | 65.0 |
| 6 | Ленинградское шоссе | 5.0 | 2.0 | 5.0 | 13.0 | 13.0 | 3.0 | 26.0 | 3.0 | 70.0 |
| 7 | Варшавское шоссе | 6.0 | NaN | 7.0 | 18.0 | 14.0 | 4.0 | 20.0 | 7.0 | 76.0 |
| 8 | Каширское шоссе | 2.0 | NaN | 10.0 | 20.0 | 16.0 | 5.0 | 19.0 | 5.0 | 77.0 |
| 9 | Дмитровское шоссе | 6.0 | 2.0 | 10.0 | 23.0 | 11.0 | 8.0 | 24.0 | 4.0 | 88.0 |
| 10 | Ленинградский проспект | 15.0 | 4.0 | 2.0 | 12.0 | 25.0 | 9.0 | 25.0 | 3.0 | 95.0 |
| 11 | Ленинский проспект | 10.0 | 3.0 | 2.0 | 26.0 | 23.0 | 5.0 | 33.0 | 5.0 | 107.0 |
| 12 | проспект Вернадского | 7.0 | 1.0 | 12.0 | 25.0 | 16.0 | 12.0 | 33.0 | 2.0 | 108.0 |
| 13 | Профсоюзная улица | 6.0 | 4.0 | 15.0 | 35.0 | 18.0 | 15.0 | 26.0 | 3.0 | 122.0 |
| 14 | проспект Мира | 11.0 | 4.0 | 21.0 | 53.0 | 36.0 | 11.0 | 45.0 | 2.0 | 183.0 |
fig = px.bar(places_by_street,
x=['бар,паб', 'булочная', 'быстрое питание', 'кафе', 'кофейня', 'пиццерия', 'ресторан', 'столовая'],
y='street',
orientation='h',
labels={
'street': 'Улица',
'value': 'Количество заведений',
'variable': 'Категория заведения'
},
title='Распределение заведений по категориям и по топ-15 улицам')
fig.show()
В топ-15 улиц по количеству заведений больше всего заведений расположено на проспекте Мира (183), а меньше всего на Пятницкой улице (48).
Найдем улицы, на которых находится только один объект общепита.
one_place_streets_list = top_streets.query('places_amt == 1')['street']
one_place_streets = places.query('street in @one_place_streets_list')
Проверим данные в этом датасете.
df_info(one_place_streets)
Первые 20 строк таблицы:
| name | category | address | district | hours | lat | lng | rating | price | avg_bill | middle_avg_bill | middle_coffee_cup | chain | seats | street | is_24_7 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 15 | дом обеда | столовая | москва, улица бусиновская горка, 2 | Северный административный округ | пн-пт 08:30–18:30; сб 10:00–20:00 | 55.885890 | 37.493264 | 4.1 | средние | Средний счёт:300–500 ₽ | 400.0 | NaN | 0 | 180.0 | улица Бусиновская Горка | False |
| 21 | 7/12 | кафе | москва, прибрежный проезд, 7 | Северный административный округ | ежедневно, 10:00–22:00 | 55.876805 | 37.464934 | 4.5 | NaN | NaN | NaN | NaN | 0 | NaN | Прибрежный проезд | False |
| 25 | в парке вкуснее | кофейня | москва, парк левобережный | Северный административный округ | ежедневно, 10:00–21:00 | 55.878453 | 37.460028 | 4.3 | NaN | NaN | NaN | NaN | 1 | NaN | парк Левобережный | False |
| 58 | coffeekaldi's | кофейня | москва, угличская улица, 13, стр. 8 | Северо-Восточный административный округ | ежедневно, 09:00–22:00 | 55.900316 | 37.570558 | 4.1 | средние | Средний счёт:500–800 ₽ | 650.0 | NaN | 1 | NaN | Угличская улица | False |
| 60 | чебуречная история | кофейня | москва, ландшафтный заказник лианозовский | Северо-Восточный административный округ | ежедневно, 10:00–22:00 | 55.899845 | 37.570488 | 4.9 | NaN | NaN | NaN | NaN | 1 | NaN | ландшафтный заказник Лианозовский | False |
| 64 | testo мания | кофейня | москва, лианозовский парк культуры и отдыха | Северо-Восточный административный округ | ежедневно, 09:00–21:00 | 55.900058 | 37.570544 | 4.1 | NaN | NaN | NaN | NaN | 0 | NaN | Лианозовский парк культуры и отдыха | False |
| 71 | cofefest | кофейня | москва, новгородская улица, 23а | Северо-Восточный административный округ | пн-пт 08:00–19:00 | 55.901799 | 37.577672 | 4.1 | NaN | NaN | NaN | NaN | 1 | NaN | Новгородская улица | False |
| 73 | веранда | ресторан | москва, парк алтуфьево | Северо-Восточный административный округ | пн-пт 11:00–22:00; сб,вс 11:00–23:00 | 55.906875 | 37.582493 | 4.2 | NaN | NaN | NaN | NaN | 1 | NaN | парк Алтуфьево | False |
| 97 | жигулевское | бар,паб | москва, бибиревская улица, 7к2 | Северо-Восточный административный округ | пн-чт 14:00–00:00; пт,сб 14:00–02:00; вс 14:00... | 55.879733 | 37.593734 | 4.5 | средние | Цена бокала пива:90–230 ₽ | NaN | NaN | 0 | NaN | Бибиревская улица | False |
| 103 | тетри | быстрое питание | москва, лианозовский проезд, вл1 | Северо-Восточный административный округ | вт-вс 09:00–19:00 | 55.896922 | 37.554929 | 4.0 | средние | Средний счёт:150–250 ₽ | 200.0 | NaN | 0 | NaN | Лианозовский проезд | False |
| 111 | алазани | ресторан | москва, челобитьевское шоссе, 10а | Северо-Восточный административный округ | ежедневно, 12:00–00:00 | 55.914074 | 37.556803 | 4.3 | выше среднего | Средний счёт:600–2000 ₽ | 1300.0 | NaN | 0 | 40.0 | Челобитьевское шоссе | False |
| 116 | алло! пицца | пиццерия | москва, костромская улица, 14б | Северо-Восточный административный округ | ежедневно, 10:00–23:00 | 55.884819 | 37.598559 | 4.3 | средние | Средний счёт:500–700 ₽ | 600.0 | NaN | 1 | 240.0 | Костромская улица | False |
| 137 | get and fly | ресторан | москва, парк ангарские пруды | Северный административный округ | ежедневно, 09:00–23:00 | 55.880350 | 37.530713 | 4.1 | NaN | NaN | NaN | NaN | 0 | NaN | парк Ангарские пруды | False |
| 157 | линии вкуса | ресторан | москва, проектируемый проезд № 5265 | Северный административный округ | ежедневно, 09:00–23:00 | 55.891971 | 37.554376 | 4.1 | NaN | Средний счёт:1000–1500 ₽ | 1250.0 | NaN | 0 | NaN | Проектируемый проезд № 5265 | False |
| 177 | арамье | булочная | москва, улица 800-летия москвы, 22, корп. 2 | Северный административный округ | ежедневно, 09:00–21:00 | 55.879392 | 37.556832 | 4.0 | NaN | NaN | NaN | NaN | 1 | 0.0 | улица 800-летия Москвы | False |
| 189 | кафе | кафе | москва, парк ангарские пруды | Северный административный округ | ежедневно, 09:00–23:00 | 55.880327 | 37.530786 | 3.2 | NaN | NaN | NaN | NaN | 0 | NaN | парк Ангарские Пруды | False |
| 192 | шаурма | кафе | москва, вагоноремонтная улица, 5, корп. 3 | Северный административный округ | ежедневно, 08:00–23:00 | 55.896548 | 37.539999 | 4.1 | NaN | NaN | NaN | NaN | 0 | NaN | Вагоноремонтная улица | False |
| 199 | мастер вкуса | ресторан | москва, мурановская улица, 9 | Северо-Восточный административный округ | пн-сб 10:00–22:00; вс 11:00–20:00 | 55.892370 | 37.598735 | 4.3 | NaN | NaN | NaN | NaN | 0 | NaN | Мурановская улица | False |
| 207 | mr. пи | ресторан | москва, улица конёнкова, 13с2 | Северо-Восточный административный округ | ежедневно, круглосуточно | 55.891269 | 37.608934 | 3.8 | NaN | NaN | NaN | NaN | 0 | NaN | улица Конёнкова | True |
| 242 | хлеб с маслом | кофейня | москва, улица грекова, 8с1 | Северо-Восточный административный округ | пн-пт 08:00–21:00; сб,вс 09:00–21:00 | 55.886047 | 37.662279 | 4.3 | NaN | NaN | NaN | NaN | 1 | NaN | улица Грекова | False |
Общая информация о таблице: <class 'pandas.core.frame.DataFrame'> Int64Index: 459 entries, 15 to 8396 Data columns (total 16 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 name 459 non-null object 1 category 459 non-null object 2 address 459 non-null object 3 district 459 non-null object 4 hours 432 non-null object 5 lat 459 non-null float64 6 lng 459 non-null float64 7 rating 459 non-null float64 8 price 182 non-null object 9 avg_bill 194 non-null object 10 middle_avg_bill 165 non-null float64 11 middle_coffee_cup 24 non-null float64 12 chain 459 non-null int64 13 seats 156 non-null float64 14 street 459 non-null object 15 is_24_7 432 non-null object dtypes: float64(6), int64(1), object(9) memory usage: 61.0+ KB None Информация о пропусках в таблице:
| Количество пропусков | % пропусков | |
|---|---|---|
| name | 0 | 0.00 |
| category | 0 | 0.00 |
| address | 0 | 0.00 |
| district | 0 | 0.00 |
| hours | 27 | 5.88 |
| lat | 0 | 0.00 |
| lng | 0 | 0.00 |
| rating | 0 | 0.00 |
| price | 277 | 60.35 |
| avg_bill | 265 | 57.73 |
| middle_avg_bill | 294 | 64.05 |
| middle_coffee_cup | 435 | 94.77 |
| chain | 0 | 0.00 |
| seats | 303 | 66.01 |
| street | 0 | 0.00 |
| is_24_7 | 27 | 5.88 |
Количество дубликатов в таблице:
0
one_place_streets.groupby('category')['name'].agg('count').sort_values()
category булочная 8 пиццерия 15 быстрое питание 23 столовая 36 бар,паб 39 кофейня 84 ресторан 94 кафе 160 Name: name, dtype: int64
В целом можно сказать, что среди заведений, которые являются единственными на улице большую часть составляют кафе, рестораны и кофейни. Также стоит отметить, что в данных по этимзаведениям в большей части отсутствует информация по ценам и количеству посадочных мест.
Посчитаем медианы средних чеков заведений, которые хранятся в столбце middle_avg_bill, для каждого района и, используя это значение в качестве ценового индикатора, построим фоновую картограмму (хороплет).
places_bill = places.groupby('district', as_index=False)['middle_avg_bill'].agg('median').sort_values(by='middle_avg_bill', ascending=False)
places_bill
| district | middle_avg_bill | |
|---|---|---|
| 1 | Западный административный округ | 1000.0 |
| 5 | Центральный административный округ | 1000.0 |
| 4 | Северо-Западный административный округ | 700.0 |
| 2 | Северный административный округ | 650.0 |
| 7 | Юго-Западный административный округ | 600.0 |
| 0 | Восточный административный округ | 575.0 |
| 3 | Северо-Восточный административный округ | 500.0 |
| 8 | Южный административный округ | 500.0 |
| 6 | Юго-Восточный административный округ | 450.0 |
Создадим новую карту Москвы и новый хороплет.
m3 = Map(location=[moscow_lat, moscow_lng], zoom_start=10, tiles='Cartodb Positron')
Choropleth(
geo_data=state_geo,
data=places_bill,
columns=['district', 'middle_avg_bill'],
key_on='feature.name',
fill_color='Greens',
fill_opacity=0.8,
legend_name='Медианный чек в заведениях по районам',
).add_to(m3)
m3
Заведения с самым высоким медианным чеком находятся в ЦАО и ЗАО (1000,00 руб.), а с самым низким - в ЮВАО (450,00 руб.). Можно отметить, что с удалением от центра снижается медианный чек в заведениях, также можно отметить, что в западной части Москвы медианный чек в заведениях выше, чем в восточной.
Общий вывод по итогам анализа данных
В представленном датасете содержится информация о 8402 объектах общественного питания Москвы. Они распределены по семи категориям: кафе, рестораны, кофейни, бары или пабы, пиццерии, быстрое питание, столовые, булочные. Более половины всех объектов приходится на категории кафе и рестораны - 2376 (28,28%) и 2042 (24,30%) соответственно. Меньше всего объектов в категориях столовая и булочная - 315 (3,75%) и 256 (3,05%) соответственно.
Больше всего мест в ресторанах и кафе - 154681 и 118494 соответствнно, а меньше всего в булочных - 13229. Стоит отметить, что в данных по количеству посадочных мест есть пропуски, это могло оказать влияние на итоговый результат.
Несетевых заведений больше, 5199 (62%), по отношению к сетевым - 3203 (38%).
Сетевыми чаще всего бывают заведения в категориях булочная, пиццерия и кофейня - в 61,33%, 52,13% и 50,96% случаев соответственно. Меньше всего сетевых заведений в категории бар,паб - 21,99%.
В топ-15 самых популярных сетей в Москве больше всего заведений категорий кафе, пиццерии, кофейни.
По общему количеству заведений, а также по количеству заведений в каждой из категорий лидирует ЦАО - 2242 заведения. Меньше всего заведений в СЗАО - 409 заведения.
Средние рейтинги заведений по категориям мало отличаются, для каждой категории средний рейтинг находятся между 4 и 4,5 баллами. Наибольший рейтинг у заведений в ЦАО - 4,4 балла, а наименьший у заведений в ЮВАО - 4,1 балла.
В топ-15 улиц по количеству заведений больше всего заведений расположено на проспекте Мира 183 заведения, а меньше всего на Пятницкой улице - 48 заведений.
В целом можно сказать, что среди заведений, которые являются единственными на улице, большую часть составляют кафе, рестораны и кофейни. Также стоит отметить, что в данных по этимзаведениям в большей части отсутствует информация по ценам и количеству посадочных мест.
Заведения с самым восоким медианным чеком находятся в ЦАО и ЗАО (1000,00 руб.), а с самым низким - в ЮВАО (450,00 руб.). Можно отметить, что с удалением от центра снижается медианный чек в заведениях, а также, что в западной части Москвы медианный чек в заведениях выше, чем в восточной.
Детализируем исследование: открытие кофейни¶
Проверим, скольковсего кофеен в датасетее.
Для начала выделим все кофейни в отдельный датасет и изучим данные.
coffee_shops = places.query('category == "кофейня"')
df_info(coffee_shops)
Первые 20 строк таблицы:
| name | category | address | district | hours | lat | lng | rating | price | avg_bill | middle_avg_bill | middle_coffee_cup | chain | seats | street | is_24_7 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 3 | dormouse coffee shop | кофейня | москва, улица маршала федоренко, 12 | Северный административный округ | ежедневно, 09:00–22:00 | 55.881608 | 37.488860 | 5.0 | NaN | Цена чашки капучино:155–185 ₽ | NaN | 170.0 | 0 | NaN | улица Маршала Федоренко | False |
| 25 | в парке вкуснее | кофейня | москва, парк левобережный | Северный административный округ | ежедневно, 10:00–21:00 | 55.878453 | 37.460028 | 4.3 | NaN | NaN | NaN | NaN | 1 | NaN | парк Левобережный | False |
| 45 | 9 bar coffee | кофейня | москва, коровинское шоссе, 41, стр. 1 | Северный административный округ | пн-пт 08:00–18:00 | 55.885837 | 37.513422 | 4.0 | NaN | NaN | NaN | NaN | 1 | 46.0 | Коровинское шоссе | False |
| 46 | cofefest | кофейня | москва, улица маршала федоренко, 6с1 | Северный административный округ | пн-пт 09:00–19:00 | 55.879934 | 37.492522 | 3.6 | NaN | NaN | NaN | NaN | 1 | NaN | улица Маршала Федоренко | False |
| 52 | cofix | кофейня | москва, улица дыбенко, 7/1 | Северный административный округ | ежедневно, 08:00–22:00 | 55.878531 | 37.479395 | 3.8 | NaN | NaN | NaN | NaN | 1 | NaN | улица Дыбенко | False |
| 53 | royal coffee | кофейня | москва, правобережная улица, 1б | Северный административный округ | ежедневно, 10:00–22:00 | 55.880622 | 37.448529 | 3.1 | NaN | NaN | NaN | NaN | 0 | 148.0 | Правобережная улица | False |
| 58 | coffeekaldi's | кофейня | москва, угличская улица, 13, стр. 8 | Северо-Восточный административный округ | ежедневно, 09:00–22:00 | 55.900316 | 37.570558 | 4.1 | средние | Средний счёт:500–800 ₽ | 650.0 | NaN | 1 | NaN | Угличская улица | False |
| 60 | чебуречная история | кофейня | москва, ландшафтный заказник лианозовский | Северо-Восточный административный округ | ежедневно, 10:00–22:00 | 55.899845 | 37.570488 | 4.9 | NaN | NaN | NaN | NaN | 1 | NaN | ландшафтный заказник Лианозовский | False |
| 64 | testo мания | кофейня | москва, лианозовский парк культуры и отдыха | Северо-Восточный административный округ | ежедневно, 09:00–21:00 | 55.900058 | 37.570544 | 4.1 | NaN | NaN | NaN | NaN | 0 | NaN | Лианозовский парк культуры и отдыха | False |
| 66 | молинари | кофейня | москва, алтуфьевское шоссе, 70, корп. 1 | Северо-Восточный административный округ | ежедневно, 10:00–22:00 | 55.887887 | 37.588294 | 4.8 | NaN | NaN | NaN | NaN | 0 | 120.0 | Алтуфьевское шоссе | False |
| 71 | cofefest | кофейня | москва, новгородская улица, 23а | Северо-Восточный административный округ | пн-пт 08:00–19:00 | 55.901799 | 37.577672 | 4.1 | NaN | NaN | NaN | NaN | 1 | NaN | Новгородская улица | False |
| 72 | лакрица | кофейня | москва, алтуфьевское шоссе, 85 | Северо-Восточный административный округ | ежедневно, 08:00–21:00 | 55.891196 | 37.585653 | 4.5 | средние | Цена чашки капучино:150–190 ₽ | NaN | 170.0 | 0 | 12.0 | Алтуфьевское шоссе | False |
| 81 | coffee way | кофейня | москва, алтуфьевское шоссе, 86, корп. 1 | Северо-Восточный административный округ | ежедневно, 09:00–22:00 | 55.897789 | 37.588189 | 4.3 | NaN | Цена чашки капучино:120–170 ₽ | NaN | 145.0 | 1 | 120.0 | Алтуфьевское шоссе | False |
| 89 | сахарочек | кофейня | москва, дмитровское шоссе, 107а, корп. 2 | Северный административный округ | пн-пт 09:00–22:00; сб 10:00–22:00; вс 10:00–21:00 | 55.879256 | 37.538444 | 4.5 | средние | Цена чашки капучино:100–200 ₽ | NaN | 150.0 | 0 | 120.0 | Дмитровское шоссе | False |
| 96 | cofefest | кофейня | москва, улица пришвина, 8 | Северо-Восточный административный округ | пн-пт 08:00–19:00 | 55.888942 | 37.595195 | 4.3 | NaN | NaN | NaN | NaN | 1 | NaN | улица Пришвина | False |
| 100 | take and wake | кофейня | москва, дмитровское шоссе, 100, стр. 2 | Северный административный округ | пн-пт 08:30–18:30 | 55.882019 | 37.546174 | 4.5 | низкие | Цена чашки капучино:150–210 ₽ | NaN | 180.0 | 1 | 120.0 | Дмитровское шоссе | False |
| 106 | вектор | кофейня | москва, алтуфьевское шоссе, 48, корп. 1 | Северо-Восточный административный округ | пн-пт 07:30–18:30 | 55.876142 | 37.588024 | 4.4 | NaN | Цена чашки капучино:80–160 ₽ | NaN | 120.0 | 0 | 120.0 | Алтуфьевское шоссе | False |
| 118 | cofefest | кофейня | москва, дубнинская улица, 40, корп. 3 | Северный административный округ | пн-пт 09:00–18:00 | 55.889336 | 37.561877 | 4.1 | NaN | NaN | NaN | NaN | 1 | NaN | Дубнинская улица | False |
| 131 | crosseat | кофейня | москва, бульвар академика ландау, 1 | Северо-Восточный административный округ | ежедневно, 09:00–21:00 | 55.920257 | 37.550906 | 4.5 | NaN | NaN | NaN | NaN | 0 | 10.0 | бульвар Академика Ландау | False |
| 139 | шеф бургер | кофейня | москва, дмитровское шоссе, 116д | Северо-Восточный административный округ | ежедневно, 10:00–22:00 | 55.901734 | 37.548499 | 4.1 | средние | Средний счёт:300 ₽ | 300.0 | NaN | 1 | 120.0 | Дмитровское шоссе | False |
Общая информация о таблице: <class 'pandas.core.frame.DataFrame'> Int64Index: 1413 entries, 3 to 8396 Data columns (total 16 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 name 1413 non-null object 1 category 1413 non-null object 2 address 1413 non-null object 3 district 1413 non-null object 4 hours 1398 non-null object 5 lat 1413 non-null float64 6 lng 1413 non-null float64 7 rating 1413 non-null float64 8 price 476 non-null object 9 avg_bill 721 non-null object 10 middle_avg_bill 200 non-null float64 11 middle_coffee_cup 521 non-null float64 12 chain 1413 non-null int64 13 seats 751 non-null float64 14 street 1413 non-null object 15 is_24_7 1398 non-null object dtypes: float64(6), int64(1), object(9) memory usage: 187.7+ KB None Информация о пропусках в таблице:
| Количество пропусков | % пропусков | |
|---|---|---|
| name | 0 | 0.00 |
| category | 0 | 0.00 |
| address | 0 | 0.00 |
| district | 0 | 0.00 |
| hours | 15 | 1.06 |
| lat | 0 | 0.00 |
| lng | 0 | 0.00 |
| rating | 0 | 0.00 |
| price | 937 | 66.31 |
| avg_bill | 692 | 48.97 |
| middle_avg_bill | 1213 | 85.85 |
| middle_coffee_cup | 892 | 63.13 |
| chain | 0 | 0.00 |
| seats | 662 | 46.85 |
| street | 0 | 0.00 |
| is_24_7 | 15 | 1.06 |
Количество дубликатов в таблице:
0
Данные содержат информацию о 1413 кофейнях города Москвы.
Для дальнейшего исследования нам необходимо иметь представление о пропусках данных в датасете coffee_shops. Столбец is_24_7 содержит около 1% пропусков, для нашего исследования это не критично, оствляем пропуски. Столбец middle_coffe_cup наоборот содержит много пропусков - 63,13%. Показатель важный для нашего исследования, но удалить такой объем данных мы не можем. Пропуски также оставляем, но будем иметь в виду, что точность этого параметра при дальнейшей обработке может быть искажена.
Изучим, как распределены кофейни по районам Москвы.
coffee_shops_by_district = coffee_shops.pivot_table(index='district', values='name', aggfunc='count').\
sort_values(by='name').reset_index()
coffee_shops_by_district.columns = (['district', 'coffee_shops_amt'])
coffee_shops_by_district['coffee_shops_share'] = round((coffee_shops_by_district['coffee_shops_amt'] /
coffee_shops_by_district['coffee_shops_amt'].sum()) * 100, 2)
coffee_shops_by_district
| district | coffee_shops_amt | coffee_shops_share | |
|---|---|---|---|
| 0 | Северо-Западный административный округ | 62 | 4.39 |
| 1 | Юго-Восточный административный округ | 89 | 6.30 |
| 2 | Юго-Западный административный округ | 96 | 6.79 |
| 3 | Восточный административный округ | 105 | 7.43 |
| 4 | Южный административный округ | 131 | 9.27 |
| 5 | Западный административный округ | 150 | 10.62 |
| 6 | Северо-Восточный административный округ | 159 | 11.25 |
| 7 | Северный административный округ | 193 | 13.66 |
| 8 | Центральный административный округ | 428 | 30.29 |
fig = px.bar(coffee_shops_by_district,
x='coffee_shops_amt',
y='district',
orientation='h',
labels={
'district': 'Район',
'coffee_shops_amt': 'Количество кофеен'
},
title='Распределение кофеен по районам')
fig.show()
Около трети всех кофеен находится в ЦАО. В топ-5 районов по количеству также входят САО, СВАО, ЮЗАО, ЗАО, ЮАО. Меньше всего кофеен - всего 4,39% - в СЗАО.
Проверим, есть ли круглосуточные кофейни.
coffee_shops_24_7 = coffee_shops.query('is_24_7 == True')['name'].count()
coffee_shops_24_7
59
Круглосуточных кофеен всего 59 - менее 5% от всех кофеен Москвы. Проверим, как распределены по районам круглосуточные и некруглосуточные кофейни.
coffee_shops_24_7_by_district = coffee_shops.pivot_table(index='district', columns='is_24_7', values='name', aggfunc='count')
coffee_shops_24_7_by_district.columns = (['not_24_7', 'is_24_7'])
coffee_shops_24_7_by_district['coffee_shops_amt'] = coffee_shops_24_7_by_district.sum(axis=1)
coffee_shops_24_7_by_district = coffee_shops_24_7_by_district.sort_values(by='coffee_shops_amt').reset_index()
coffee_shops_24_7_by_district
| district | not_24_7 | is_24_7 | coffee_shops_amt | |
|---|---|---|---|---|
| 0 | Северо-Западный административный округ | 60 | 2 | 62 |
| 1 | Юго-Восточный административный округ | 87 | 1 | 88 |
| 2 | Юго-Западный административный округ | 87 | 7 | 94 |
| 3 | Восточный административный округ | 97 | 5 | 102 |
| 4 | Южный административный округ | 129 | 1 | 130 |
| 5 | Западный административный округ | 139 | 9 | 148 |
| 6 | Северо-Восточный административный округ | 154 | 3 | 157 |
| 7 | Северный административный округ | 186 | 5 | 191 |
| 8 | Центральный административный округ | 400 | 26 | 426 |
fig = px.bar(coffee_shops_24_7_by_district,
x=['not_24_7', 'is_24_7'],
y='district',
orientation='h',
labels={
'district': 'Район',
'value': 'Количество кофеен',
'variable': 'Круглосуточный режим работы'
},
title='Распределение кофеен по времени работы и по районам')
fig.show()
Около половины всех круглосуточных кофеен находися в ЦАО, остальные распредлены по всем другим районам в незначительных количествах.
Ранее было расчитано, что сетевых и несетевых кофеен в Москве примерно поровну - 720 и 693 кофейни соответственно. Проверим, как такие кофейни распрелены по районам.
coffee_shops_chain_by_district = coffee_shops.pivot_table(index='district', columns='chain', values='name', aggfunc='count')
coffee_shops_chain_by_district.columns = (['not_chain', 'is_chain'])
coffee_shops_chain_by_district['coffee_shops_amt'] = coffee_shops_chain_by_district.sum(axis=1)
coffee_shops_chain_by_district = coffee_shops_chain_by_district.sort_values(by='coffee_shops_amt').reset_index()
coffee_shops_chain_by_district
| district | not_chain | is_chain | coffee_shops_amt | |
|---|---|---|---|---|
| 0 | Северо-Западный административный округ | 28 | 34 | 62 |
| 1 | Юго-Восточный административный округ | 60 | 29 | 89 |
| 2 | Юго-Западный административный округ | 46 | 50 | 96 |
| 3 | Восточный административный округ | 54 | 51 | 105 |
| 4 | Южный административный округ | 65 | 66 | 131 |
| 5 | Западный административный округ | 57 | 93 | 150 |
| 6 | Северо-Восточный административный округ | 80 | 79 | 159 |
| 7 | Северный административный округ | 96 | 97 | 193 |
| 8 | Центральный административный округ | 207 | 221 | 428 |
fig = px.bar(coffee_shops_chain_by_district,
x=['not_chain', 'is_chain'],
y='district',
orientation='h',
labels={
'district': 'Район',
'value': 'Количество заведений',
'variable': 'Принадлежность кофеен к сетям'
},
title='Распределение кофеен по принадлежности к сетям и по районам')
fig.show()
В целом можно сказать, что и по районам сетевые и несетевые кофейни распределены равномерно. Районов, в каторых было бы значительно больше кофеен одного типа, нет.
Изучем распределение средних рейтингов кофеен по районам.
coffee_shops_rating = coffee_shops.groupby('district', as_index=False)['rating'].agg('mean').\
sort_values(by='rating', ascending=False)
coffee_shops_rating
| district | rating | |
|---|---|---|
| 5 | Центральный административный округ | 4.336449 |
| 4 | Северо-Западный административный округ | 4.325806 |
| 2 | Северный административный округ | 4.291710 |
| 7 | Юго-Западный административный округ | 4.283333 |
| 0 | Восточный административный округ | 4.282857 |
| 8 | Южный административный округ | 4.232824 |
| 6 | Юго-Восточный административный округ | 4.225843 |
| 3 | Северо-Восточный административный округ | 4.216981 |
| 1 | Западный административный округ | 4.195333 |
Построим визуализацию.
plt.figure(figsize=(15, 9))
sns.boxplot(x='district', y='rating', data=places, order=coffee_shops.groupby('district')['rating'].
mean().sort_values().index, palette='Set2')
plt.xlabel('Район')
plt.ylabel('Рейтинг заведения')
plt.xticks(rotation=45)
plt.title('Распределение средних рейтингов кофеен по районам');
Также построим фоновую картограмму среднего рейтинга кофеен по районам.
Создадим новую карту Москвы и новый хораплет.
m4 = Map(location=[moscow_lat, moscow_lng], zoom_start=10, tiles='Cartodb Positron')
Choropleth(
geo_data=state_geo,
data=coffee_shops_rating,
columns=['district', 'rating'],
key_on='feature.name',
fill_color='YlOrRd',
fill_opacity=0.8,
legend_name='Средний рейтинг кофеен по районам',
).add_to(m4)
m4
Наибольший средний рейтинг кофеен в ЦАО, наименьший - в ЗАО.
Посчитаем медианы средних стоимостей чашки капучино, которые хранятся в столбце middle_coffee_cup, для каждого района и, используя это значение в качестве ценового индикатора, построим фоновую картограмму (хороплет).
coffee_shops_bill = places.groupby('district', as_index=False)['middle_coffee_cup'].agg('median').sort_values(by='middle_coffee_cup', ascending=False)
coffee_shops_bill
| district | middle_coffee_cup | |
|---|---|---|
| 7 | Юго-Западный административный округ | 197.0 |
| 5 | Центральный административный округ | 190.0 |
| 1 | Западный административный округ | 187.0 |
| 3 | Северо-Восточный административный округ | 162.5 |
| 2 | Северный административный округ | 159.0 |
| 4 | Северо-Западный административный округ | 150.0 |
| 8 | Южный административный округ | 149.5 |
| 6 | Юго-Восточный административный округ | 145.0 |
| 0 | Восточный административный округ | 135.0 |
Создадим новую карту Москвы и новый хораплет.
m5 = Map(location=[moscow_lat, moscow_lng], zoom_start=10, tiles='Cartodb Positron')
Choropleth(
geo_data=state_geo,
data=coffee_shops_bill,
columns=['district', 'middle_coffee_cup'],
key_on='feature.name',
fill_color='YlGn',
fill_opacity=0.8,
legend_name='Медианный чек за чашку капучино в кофейнях по районам',
).add_to(m5)
m5
В топ-3 района по уровню медианной цены чашки капучино входят ЮЗАО, ЦАО и ЗАО, цена чашки капучино от 197 до 187 рублей. Самая низкая медианная цена чашки капучино в ВАО - 135 рублей.
Рекомендации по открытию новой кофейни
Исходя из изученных данных можно сказать, что рынок кофеен в Москве достаточно насыщен - 16,81% от всех заведений общественного питания это кофейни. Впрочем, это не говорит о том, что потенциал этого направления исчерпан, что подтверждает статистика его непрерывного роста в последние годы. Учитывая желание инвесторов открыть крутое и в каком-то смысле необычное место, можно порекомендовать открытие несетевой круглосуточной кофейни в Западном административном округе Москвы. В пользу этого решения говорят следующие результаты исследования:
- ЗАО занимает только 5 место по количеству заведений общественного питания по Москве.
- ЗАО занимает только 4 место по количеству кофеен - 10,62% от всех кофеен Москвы.
- Количество круглосуточных кофеен в ЗАО, как и в целом по Москве, очень мало.
- Средний рейтинг кофеен в ЗАО самый низкий по Москве - 4,2 балла.
- При этом медианный уровень стоимости чашки капучино в ЗАО находится на втором месте по Москве, уступая лишь ЦАО, который является самым дорогим районом Москвы по ценам в заведениях общественного питания в целом и стоимости чашки капучино в кофейнях в частности. Стоимость чашки капучино в ЗАО заметно выше, чем во всех остальные районы, кроме соседнего ЮЗАО, который замыкает топ-3 районов по этому показателю.
Таким образом, при достижении баланса между конкурентным уровнем цен и высоким уровнем сервиса, описанный выше подход имеет высокие шансы на успешную реализацию.
Презентация¶